#include "uartwork.h"

uartWork::uartWork() {

   //串口关闭标志
  isConnectFlag = false;
  //建立一个串口对象
  currSerial = new QSerialPort();
   //创建子线程
  currThread = new QThread();
  //创建定时器对象
  rcvDataTimer = new QTimer();
  //加入到子线程
  this->moveToThread(currThread);
  currSerial->moveToThread(currThread);
  rcvDataTimer->moveToThread(currThread);
  //绑定信号槽

  //如果串口错误发出错误信号，并执行对应的槽函数
  connect(currSerial, static_cast<void(QSerialPort::*)(QSerialPort::SerialPortError)>(&QSerialPort::error),
        [=](QSerialPort::SerialPortError error){
            errorOccurredqq(error);
  });
  //如果串口接收到数据，执行数据接收的处理槽
  connect(currSerial, &QSerialPort::readyRead, this, &uartWork::readyRead,
          Qt::QueuedConnection);
//  //开启线程
//  currThread->start();

  //设置定时时间，精确定时
  rcvDataTimer->setInterval(30);
  rcvDataTimer->setTimerType(Qt::PreciseTimer);
  //读取数据的时间
  connect(rcvDataTimer, &QTimer::timeout, this, &uartWork::timerOut,
          Qt::QueuedConnection);
}

//销毁对象，即关闭串口退出程序
uartWork::~uartWork() {
  rcvDataTimer->stop();
  delete rcvDataTimer;
  if (currSerial->isOpen()) {
    currSerial->clear();
    currSerial->close();
    emit openError(false);
  }

  if (currThread->isRunning())
  {
    currThread->quit();
    currThread->wait();
    while (true == currThread->isRunning());
  }
  currSerial->deleteLater();
  currThread->deleteLater();
}



void uartWork::updateComCfg(comcfg_t cfg) {

  currentCfg.portNum = cfg.portNum;
  currentCfg.baudRate = cfg.baudRate;
  currentCfg.dataBits = cfg.dataBits;
  currentCfg.paritys = cfg.paritys;
  currentCfg.stopBits = cfg.stopBits;
  /* 通知打开串口 */
  openUart();
}

//开启线程
void uartWork::startThread() {
  if (false == currThread->isRunning()) {

      QString LogInfo;
      LogInfo.sprintf("%p", QThread::currentThread());
      qDebug() <<"串口线程ID：" + LogInfo << endl;
      currThread->start();
  }
}
//关闭串口
void uartWork::stopThread()
{
  if (currSerial->isOpen())
  {

    currSerial->clear();
    currSerial->close();
    emit openError(false);

  }
}

//读取完向主线程发送信号
void uartWork::timerOut()
{
  if (sendArray.isEmpty())
    return;
  rcvDataTimer->stop();
  emit readyread(sendArray);
  sendArray.clear();
}


//读取数据在子线程中执行
void uartWork::readyRead()
{
  QString LogInfo;
  LogInfo.sprintf("%p", QThread::currentThread());
  qDebug() <<"串口接收数据线程ID：" + LogInfo << endl;

  QByteArray data = currSerial->readAll();
  if (rcvDataTimer->isActive())
  {
    rcvDataTimer->stop();
  }
  if (true == data.isEmpty())
    return;
  sendArray += data;
  rcvDataTimer->start(30);
}
//打开串口
void uartWork::openUart()
{

  if (currSerial->isOpen())
  {
    currSerial->clear();
    currSerial->close();
  }
  currSerial->setPortName(QString(currentCfg.portNum));
  currSerial->setBaudRate(currentCfg.baudRate);
  currSerial->setDataBits(currentCfg.dataBits);
  currSerial->setParity(currentCfg.paritys);
  currSerial->setStopBits(currentCfg.stopBits);
  openFlag = currSerial->open(QIODevice::ReadWrite);
  emit openError(openFlag);
}
//发送数据
void uartWork::writeData(QByteArray data)
{

  QString LogInfo;
  LogInfo.sprintf("%p", QThread::currentThread());
  qDebug() <<"串口发送数据线程ID：" + LogInfo << endl;
  if ((true == currSerial->isOpen()) && (false == data.isEmpty()))
  {
    currSerial->write(data);
  }
}
//错误处理
void uartWork::errorOccurredqq(QSerialPort::SerialPortError error)
{
    switch ((int)error)
    {
    case 0:
      /* 没有错误 */
      emit openError(true);
      break;
    case 1:
      /* 打开一个不存在的设备 */
      currSerial->close();
      emit errOccurred(QString("打开一个不存在的设备!"));
      emit openError(false);
      break;
    case 2:
      /* 无权限打开一个 */
      currSerial->close();
      emit errOccurred(QString("无权限打开设备!"));
      emit openError(false);
      break;
    case 3:
      /* 打开一个已经打开的设备 */
      emit errOccurred(QString("设备已打开!"));
      emit openError(false);
      break;
    case 7:
      /* 写入数据时发生的i/o错误 */
      currSerial->close();
      emit errOccurred(QString("写数据错误!"));
      openUart();
      break;
    case 8:
      /* 读取数据时发生了i/o错误 */
      currSerial->close();
      emit errOccurred(QString("读数据错误!"));
      openUart();
      break;
    case 9:
      /* 设备意外拔出,会发生i/o错误 */
      currSerial->close();
      emit errOccurred(QString("串口已拔出!"));
      emit openError(false);
      break;
    case 11:
      /* 未知错误 */
      currSerial->close();
      emit errOccurred(QString("发生未知错误!"));
      emit openError(false);
      break;
    }
}


